﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Collections.Specialized;
using System.Web.Caching;

namespace Mindfor.Web
{
	/// <summary>
	/// Provides captcha text validation.
	/// </summary>
	[AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
	public class CaptchaValidateAttribute : FilterAttribute, IAuthorizationFilter
	{
		/// <summary>
		/// Gets or sets error message that applied to model state when captcha key is wrong.
		/// </summary>
		public string WrongKeyError { get; set; }

		/// <summary>
		/// Gets or sets error message that applied to model state when captcha text is wrong.
		/// </summary>
		public string WrongTextError { get; set; }

		/// <summary>
		/// Initializes new instance.
		/// </summary>
		public CaptchaValidateAttribute()
		{
			WrongKeyError = "Captcha system key is invalid";
			WrongTextError = "Captcha text is invalid";
		}

		/// <summary>
		/// Initializes new instance.
		/// </summary>
		/// <param name="wrongTextError">Error message that applied to model state when captcha text is wrong.</param>
		public CaptchaValidateAttribute(string wrongTextError)
			: this()
		{
			WrongTextError = wrongTextError;
		}

		/// <summary>
		/// Called by the MVC framework when authorization required.
		/// </summary>
		public void OnAuthorization(AuthorizationContext filterContext)
		{
			// get user key and text
			string fKey = filterContext.HttpContext.Request[CaptchaManager.HtmlKeyName];
			string fText = filterContext.HttpContext.Request[CaptchaManager.HtmlTextName];

			// validate key and get corrent text
			string correctText = null;
			ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState;
			try
			{
				Cache c = filterContext.RequestContext.HttpContext.Cache;
				if (c[fKey] == null)
					throw new InvalidOperationException();
				else
					c.Remove(fKey);
				correctText = CaptchaManager.DecryptTextFromKey(fKey);
			}
			catch
			{
				modelState.AddModelError(CaptchaManager.HtmlKeyName, WrongKeyError);
				return;
			}
			
			// validate text
			if (fText.ToLower() != correctText.ToLower())
			{
				modelState.AddModelError(CaptchaManager.HtmlTextName, WrongTextError);
			}
		}
	}
}
